﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Mvvm;
using Prism.Commands;
using Server.BLL;
using Server.Common;
using Models;
using System.Windows;
using Taxhui.Utils.Network.Tcp;
using Taxhui.Utils.Network.Tcp.TcpConfig;
using Taxhui.Utils.Network.Tcp.NetSession;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.Timers;
using Prism.Events;
using Server.DAL;

namespace Server.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        #region 绑定属性

        //端口
        private int _serverPort;

        public int ServerPort
        {
            get { return _serverPort; }
            set { SetProperty(ref _serverPort, value, "ServerPort"); }
        }

        //开机启动状态
        private bool _autoRunState;

        public bool AutoRunState
        {
            get { return _autoRunState; }
            set { SetProperty(ref _autoRunState, value, "AutoRunState"); }
        }

        //自动启动状态
        private bool _autoStartState;

        public bool AutoStartState
        {
            get { return _autoStartState; }
            set { SetProperty(ref _autoStartState, value, "AutoStartState"); }
        }

        //启动最小化状态
        private bool _autoMinimizeState;

        public bool AutoMinimizeState
        {
            get { return _autoMinimizeState; }
            set { SetProperty(ref _autoMinimizeState, value, "AutoMinimizeState"); }
        }

        //服务器启动按钮状态
        private bool _startState;

        public bool StartState
        {
            get { return _startState; }
            set { SetProperty(ref _startState, value, "StartState"); }
        }

        //服务器停止按钮状态
        private bool _stopState;

        public bool StopState
        {
            get { return _stopState; }
            set { SetProperty(ref _stopState, value, "StopState"); }
        }

        //窗口状态
        private WindowState _winState;

        public WindowState WinState
        {
            get { return _winState; }
            set { SetProperty(ref _winState, value, "WinState"); }
        }

        //窗口可见状态
        private Visibility _winVisible;

        public Visibility WinVisible
        {
            get { return _winVisible; }
            set { SetProperty(ref _winVisible, value, "WinVisible"); }
        }

        //在线列表
        private ObservableCollection<SessionModel> _onlineList;

        public ObservableCollection<SessionModel> OnlineList
        {
            get { return _onlineList; }
            set { SetProperty(ref _onlineList, value, "OnlineList"); }
        }

        //日志框内容
        private string _logTxt;

        public string LogTxt
        {
            get { return _logTxt; }
            set { SetProperty(ref _logTxt, value, "LogTxt"); }
        }

        #endregion 绑定属性

        #region 属性

        private ServerAgent _server;
        private Timer _refreshTimer;
        private IEventAggregator _ea;

        #endregion 属性

        #region 命令

        public DelegateCommand StartCommand { get; private set; }
        public DelegateCommand StopCommand { get; private set; }
        public DelegateCommand SaveSetCommand { get; private set; }

        #endregion 命令

        #region 构造函数

        public MainWindowViewModel(IEventAggregator ea)
        {
            _ea = ea;
            _ea?.GetEvent<LogEvent>().Subscribe(AddLog);
            StartCommand = new DelegateCommand(StartServer);
            StopCommand = new DelegateCommand(StopServer);
            SaveSetCommand = new DelegateCommand(SaveSetting);
            OnlineList = new ObservableCollection<SessionModel>();
            ResetState();
            if (AutoStartState)
                StartServer();
            _refreshTimer = new Timer
            {
                AutoReset = true,
                Enabled = true,
                Interval = 3000
            };
            _refreshTimer.Elapsed += RefreshEvent;
            _refreshTimer.Start();
        }

        #endregion 构造函数

        #region 方法

        private void SaveSetting()
        {
            Comm.Cfg.AutoMin = AutoMinimizeState;
            Comm.Cfg.AutoRun = AutoRunState;
            Comm.Cfg.AutoStart = AutoStartState;
            Comm.Cfg.ServerPort = ServerPort;
            Comm.Cfg.SaveConfig(AppDomain.CurrentDomain.BaseDirectory + "config.xml");
        }

        //更新日志框
        private void AddLog(string log)
        {
            if (LogTxt.Length > 3000)
                LogTxt = "";
            LogTxt += log;
        }

        //刷新在线列表
        private void RefreshEvent(object sender, ElapsedEventArgs e)
        {
            try
            {
                System.Windows.Application.Current.Dispatcher.Invoke(RefreshOnline);
            }
            catch (Exception)
            {
            }
        }

        private void RefreshOnline()
        {
            OnlineList.Clear();
            OnlineList.AddRange(Comm.Onlines.Values.ToList());
        }

        //初始状态
        private void ResetState()
        {
            ServerPort = Comm.Cfg.ServerPort;
            AutoRunState = Comm.Cfg.AutoRun;
            AutoStartState = Comm.Cfg.AutoStart;
            AutoMinimizeState = Comm.Cfg.AutoMin;
            StartState = true;
            StopState = false;
            WinState = AutoMinimizeState ? WindowState.Minimized : WindowState.Normal;
            WinVisible = AutoMinimizeState ? Visibility.Hidden : Visibility.Visible;
        }

        //重置server状态
        private void ResetServer()
        {
            if (_server != null)
            {
                _server.ClearConnections(true);
                _server.Dispose();
            }
        }

        //启动服务
        private void StartServer()
        {
            try
            {
                LogTxt += "正在检查数据库...";
                if (!SysSrv.CheckVerTable())
                {
                    LogTxt += "准备升级\r\n";
                    SysSrv.CreateVersionTable();
                }
                else
                {
                    LogTxt += "完成\r\n";
                }
                bool upOK = false;
                while (!upOK)
                {
                    string ver = SysSrv.GetDBVer();
                    switch (ver)
                    {
                        case "":
                            LogTxt += "升级数据库到1.0.0.1...";
                            SysSrv.UpdateDBVer(Properties.Resources.DBNullTo1000);//升级到1.0.0.1
                            LogTxt += "完成\r\n";
                            break;

                        case "1.0.0.0":
                            LogTxt += "升级数据库到1.0.0.1...";
                            SysSrv.UpdateDBVer(Properties.Resources.DBNullTo1000);//升级到1.0.0.1
                            LogTxt += "完成\r\n";
                            break;

                        case "1.0.0.1":
                            LogTxt = "升级数据库到1.0.0.2...";
                            SysSrv.UpdateDBVer(Properties.Resources.DB1001To1002);//升级到1.0.0.2
                            LogTxt = "完成\r\n";
                            break;

                        default:
                            upOK = true;
                            break;
                    }
                }
                LogTxt += "正在启动服务器...\r\n";
                StartState = false; StopState = false;
                ServerConfig cfg = new ServerConfig
                {
                    AutoHeartBeat = true,
                    CheckDisconnect = true,
                    CheckDisconnectTimeout = 15,
                    CompressTransferFromPacket = true,
                    KeepAlive = true,
                    KeepAliveInterval = 5000,
                    KeepAliveSpanTime = 5000,
                    NoDelay = true,
                    PendingConnectionBacklog = 20,
                    ReceiveBufferSize = 8192,
                    ReceiveTimeout = TimeSpan.Zero,
                    SendBufferSize = 8192,
                    SendTimeout = TimeSpan.Zero
                };
                _server = TcpFactory.CreateServerAgent(SessionType.Packet, cfg, Server_Event);
                _server.Listen("0.0.0.0", ServerPort);
                LogTxt += "启动服务完成\r\n";
                StartState = false;
                StopState = true;
            }
            catch (Exception ex)
            {
                LogTxt += "失败\r\n错误：" + ex.Message;
                StartState = true;
                StopState = false;
            }
        }

        //关闭服务器
        private void StopServer()
        {
            try
            {
                StartState = false; StopState = false;
                LogTxt += "关闭服务器...";
                ResetServer();
                LogTxt += "完成\r\n";
            }
            catch (Exception ex)
            {
                LogTxt += "失败\r\n错误:" + ex.Message;
            }
            StartState = true; StopState = false;
        }

        //接收数据事件
        private void Server_Event(CompleteNotify e, Session session)
        {
            switch (e)
            {
                case CompleteNotify.OnConnected:
                    _ea.GetEvent<LogEvent>().Publish("客户端连接\r\n");
                    break;

                case CompleteNotify.OnSend:
                    break;

                case CompleteNotify.OnDataReceiveing:
                    break;

                case CompleteNotify.OnDataReceived:
                    HandleData(session);
                    break;

                case CompleteNotify.OnClosed:
                    _ea.GetEvent<LogEvent>().Publish($"[{session.SessionId}]客户端断开\r\n");
                    break;

                default:
                    break;
            }
        }

        //处理数据
        private async void HandleData(Session sess)
        {
            if (null == sess.CompletedBuffer)
                return;
            RetModel rm = await Task.Run(() =>
            {
                DataHandle d = new DataHandle();
                return d.HandlerData(sess.CompletedBuffer);
            });
            //回复
            string retStr = JsonConvert.SerializeObject(rm);
            byte[] backData = Encoding.UTF8.GetBytes(retStr);
            sess?.SendAsync(backData);
        }

        #endregion 方法
    }
}